use ash::vk::{self, CommandBuffer};

use crate::{system::{render::{camera::PerFrameUniformData, render_pass::{post_render_pass::{self, PostRenderPassCreateInfo}, mesh_render_pass::MeshRenderPass}, render_scene::RenderScene}, MAX_FRAMES_IN_FLIGHT}, vulkan::{vk_struct::{VkDescriptorSet, VkImage, VkMappedBuffer, VkPipeline, VkSwapchain, VkTexture}, VkConfig, VkContext}, VK_LOGI};

use self::{camera::Camera, render_pass::post_render_pass::PostRenderPass};

use super::window::WindowSystem;

pub mod sync;
pub mod render_tick;
pub mod render_pass;
pub mod camera;
pub mod render_scene;

pub struct RenderSystemCreateInfo<'a> {
    pub window_system: &'a WindowSystem
}

/// 单次渲染流程中需要的同步量 <br>
/// Fence通常是用来同步QueueSubmit的，也就是同步Queue操作和Host端执行顺序的<br>
/// 当QueueSubmit执行完毕之后，提交时Hold的Fence就会变成Signaled，Host端另一处执行WaitFence就可以等到这个Fence变成Signaled，然后再ResetFence就可以继续用了<br>
/// Semaphore通常是用来同步一些操作的<br>
/// 最明显的就是queue_submit的时候，不仅仅需要提供一个Fence，还需要提供这个操作需要Wait和Signal的Semaphore
pub struct FrameSyncObject {
    /// 向Swapchain申请Image的同步量
    pub image_available_semaphore   : vk::Semaphore,
    /// 渲染完毕的同步量
    pub render_finished_semaphore   : vk::Semaphore,
    /// Queue执行完毕的同步量
    pub submit_fence                : vk::Fence,
}

/// 渲染系统
/// 1. vulkan core功能在这里，作为Rhi使用
/// 2. 初始化渲染功能需要的组件，并且执行渲染tick
/// 3. 管理渲染资源
pub struct RenderSystem {
    //
    pub vk_context                  : VkContext,

    swapchain                       : VkSwapchain,
    frame_sync_objects              : Vec<FrameSyncObject>,
    frame_command_buffers           : Vec<CommandBuffer>, 
    
    pub camera                      : Camera,
    pub render_scene                : RenderScene,

    pub post_render_pass            : PostRenderPass,
    pub mesh_render_pass            : MeshRenderPass,

    pub current_frame_index         : usize
}

impl RenderSystem {
    pub fn new(vk_config: &mut VkConfig, render_system_ci: &RenderSystemCreateInfo) -> Self {
        // Init Rhi
        VK_LOGI!("START INIT VkContext");
        let vk_context = VkContext::new(vk_config, render_system_ci.window_system);
        VK_LOGI!("END   INIT VkContext"); 
    
        // Init Application Data
        VK_LOGI!("START INIT Application");
        // 屏幕显示部分
        let camera                      = Camera::default();
        let swapchain                   = vk_context.create_swapchain();
        let swapchain_extent            = swapchain.get_extent();

        // Setup Render Scene
        let render_scene                = RenderScene::new(&vk_context);
        
        // Setup Software Renderpass
        let mesh_render_pass            = MeshRenderPass::new(&vk_context, &swapchain);

        let post_render_pass_ci         = PostRenderPassCreateInfo {
            swapchain           : &swapchain,
            input_texture       : mesh_render_pass.get_output_texture()
        };
        let post_render_pass            = PostRenderPass::new(&vk_context, post_render_pass_ci);

        // Sync Variable & Command Variable
        let frame_command_buffers       = vk_context.create_command_buffers(MAX_FRAMES_IN_FLIGHT);
        let frame_sync_objects          = Self::create_sync_objects(&vk_context);
        VK_LOGI!("END   INIT Application");

        Self {
            vk_context                  : vk_context,

            swapchain                   : swapchain,

            frame_command_buffers       : frame_command_buffers,
            frame_sync_objects          : frame_sync_objects,

            camera                      : camera,
            render_scene                : render_scene,
            mesh_render_pass            : mesh_render_pass,
            post_render_pass            : post_render_pass,

            current_frame_index         : 0
        }
    }
}